home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / modelers / geomview / source.lha / Geomview / src / bin / geomutil / ucd / anytoucd.c < prev    next >
C/C++ Source or Header  |  1993-11-04  |  11KB  |  444 lines

  1. /* File:    anytoucd.c:
  2.    Author:    Charlie Gunn originally
  3.                 
  4.    read a OOGL object on stdin, and write ucd format on stdout.
  5. */
  6. #include "vec4.h"
  7. #include "geom.h"
  8. #include "3d.h"
  9. #include "polylistP.h"
  10. #include "plutil.h"
  11. #include <stdio.h>
  12. #include "time.h"
  13.  
  14. extern Poly *getstack();    /* in stack.c */
  15.  
  16.  
  17. #define MAXV    64
  18.  
  19. /*
  20. #define DEBUG
  21. */
  22.  
  23. #define CAVE    1
  24. #define    VEX    0
  25.     static int debug = 0;
  26.  
  27. #define INSIDE(line, point)    \
  28.     ((line.a*(point)->x + line.b*(point)->y + line.c) <= 0)
  29. #define INSIDE2(line, point)    \
  30.     (line.a*(point)->x + line.b*(point)->y + line.c) 
  31.  
  32.     struct polygon {
  33.     int nv;
  34.     unsigned int new:1;
  35.     Vertex *vlist[MAXV];
  36.     HPoint3 vlistxy[MAXV];
  37.     short inout[MAXV];
  38.     Transform to_xy;    
  39.     } currpoly;
  40.  
  41.     struct line {
  42.     float a,b,c,angle;
  43.     };
  44.  
  45. typedef struct polygon polygon;
  46. typedef struct line line;
  47.  
  48. void
  49. myconvert(CP, cp)
  50. Poly *CP;
  51. polygon *cp;
  52. {
  53.     int i;
  54.     cp->nv = CP->n_vertices;
  55.     for (i=0; i<cp->nv; ++i)
  56.     cp->vlist[i] = CP->v[i];
  57.     cp->new = 1;
  58. }
  59.  
  60. polygon *
  61. chopup (pp, PP)
  62. polygon *pp;
  63. Poly *PP;
  64. {
  65.     int oc, nc, n, i ;
  66.     int cutcount = 0, convex, orient;
  67.     line edges[MAXV];
  68.     Transform m;
  69.     double tt, dangle, sum;
  70.     polygon *newpoly; 
  71.  
  72.     if (debug){
  73.     fprintf(stderr,"Entering chopup with %d vertices \n",pp->nv);
  74.     for (i=0; i<pp->nv; ++i)
  75.         fprintf(stderr,"%f %f %f \n",pp->vlist[i]->pt.x, pp->vlist[i]->pt.y, pp->vlist[i]->pt.z);
  76.     }
  77.  
  78.     if (pp->nv <= 4 && pp->nv > 1)    
  79.     {
  80.     PP->n_vertices = pp->nv;
  81.     for (i=0; i<pp->nv; ++i)    
  82.         PP->v[i] = pp->vlist[i];
  83.     if (push(PP) == 0)
  84.         OOGLError(1,"anytoucd: unable to push polygon\n");
  85.     return(NULL);
  86.     }
  87.     else if (pp->nv == 1) 
  88.     {
  89.     return(NULL);
  90.     }
  91.  
  92.     else {        /* something to chop */
  93.  
  94.     newpoly = OOGLNew(polygon);
  95.     n = pp->nv;
  96.   if (pp->new)
  97.     {
  98.     /* need to work in the x,y plane, so compute approp. tforms */
  99.     for (i=0; i<n; ++i)    /* may need to hunt for independent vectors */
  100.     if (make_tform(&pp->vlist[i]->pt, &pp->vlist[(i+1)%n]->pt, &pp->vlist[(i+2)%n]->pt, pp->to_xy) >= 0) break;;
  101.     TmInvert(pp->to_xy, pp->to_xy);
  102.  
  103.     for (i=0; i<pp->nv; ++i)
  104.     HPt3Transform(pp->to_xy, &pp->vlist[i]->pt, &pp->vlistxy[i]);
  105.     pp->new = 0;
  106.     }
  107.  
  108.  
  109.     {
  110.     double dx, dy;
  111.     for (i=0; i<pp->nv; ++i)
  112.     {
  113.     dx = pp->vlistxy[(i+1)%n].x - pp->vlistxy[i].x;    
  114.     dy = pp->vlistxy[(i+1)%n].y - pp->vlistxy[i].y;    
  115.     edges[i].a = dy;
  116.     edges[i].b = -dx;
  117.     edges[i].c = -(edges[i].a*pp->vlistxy[i].x+edges[i].b*pp->vlistxy[i].y);
  118.     edges[i].angle = atan2(dy,dx);
  119.     if (debug)
  120.     fprintf(stderr,"edge %d: angle %f\n",i,edges[i].angle);
  121.     }
  122.     }
  123.  
  124.     /* armed with this info, identify concave and convex bndy pts*/
  125.     for (sum = 0.0, i=0; i<pp->nv; ++i)
  126.     {
  127.     dangle = edges[i].angle - edges[(i-1+n)%n].angle ;
  128.     /* clip to (-PI, +PI) */
  129.     while (dangle < -PI)     dangle += 2*PI;
  130.     while (dangle > PI)     dangle -= 2*PI;
  131.     sum += dangle;
  132.     if (dangle > 0)        pp->inout[i] = VEX;
  133.     else             pp->inout[i] = CAVE;
  134.     }
  135.     
  136.     if (debug)
  137.         fprintf(stderr,"Total angle change is %f\n",sum);
  138.     if (sum > 0 ) orient = 1;
  139.     else       orient = -1;
  140.     for (convex = 1, i=0; i<pp->nv; ++i)
  141.     {
  142.     if (orient == -1)    
  143.         {
  144.             pp->inout[i] = 1 - pp->inout[i];
  145.         edges[i].a *= -1;
  146.         edges[i].b *= -1;
  147.         edges[i].c *= -1;
  148.         }
  149.     if (pp->inout[i] == CAVE)    convex = 0;
  150.     }
  151.  
  152.     if (debug)
  153.     if (convex) fprintf(stderr,"Polygon is convex\n");
  154.  
  155.     /* next look for triangles to chop off */
  156.     {
  157.     line cutcorner;
  158.     double a,b,c,angle, dx, dy;    
  159.     int cutoff, j, jj,ni, pi, oc, nc;
  160.     double d0, d1, d2;
  161.  
  162.     for (nc = 0, oc=0; oc<pp->nv-1; ++oc, ++nc)
  163.     {
  164.     /* copy out current vertex */
  165.     newpoly->vlist[nc] = pp->vlist[oc];
  166.     HPt3Copy(&pp->vlistxy[oc], &newpoly->vlistxy[nc]);
  167.     if (pp->inout[(oc+1)%n] == VEX)
  168.       {
  169.       cutoff = 1;        /* default is to cut if off */
  170.       if (!convex)
  171.         {
  172.         pi = oc;
  173.         ni = (oc+2)%n;
  174.         dx = pp->vlistxy[(oc+2)%n].x - pp->vlistxy[oc].x;
  175.         dy = pp->vlistxy[(oc+2)%n].y - pp->vlistxy[oc].y;
  176.         /* orient this line to run from v2 to v0, to agree with edges */
  177.         cutcorner.a = -dy*orient;
  178.         cutcorner.b = dx*orient;
  179.         cutcorner.c = -(cutcorner.a*pp->vlistxy[(oc+2)%n].x+cutcorner.b*pp->vlistxy[(oc+2)%n].y);
  180.         cutcorner.angle = -atan2(dy,dx);
  181.         /* check for concave pts inside this triangle */
  182.         /* don't check the vertices of this triangle */
  183.               for ( j=0, jj=oc+3; j<pp->nv-3 && cutoff; ++j,++jj)
  184.         {
  185.         if (jj == pp->nv) jj = 0;
  186.         if ( pp->inout[jj] == CAVE )
  187.             {
  188.             if (INSIDE(cutcorner,&pp->vlistxy[jj]) &&
  189.             INSIDE(edges[oc], &pp->vlistxy[jj]) &&
  190.             INSIDE(edges[(oc+1)%n], &pp->vlistxy[jj]))
  191.             {
  192.     if (debug)
  193.     fprintf(stderr,"vertex %d is inside cutoff corner %d %d %d\n",jj, oc, oc+1, oc+2);
  194.             cutoff = 0; 
  195.             }
  196.             }
  197.         }
  198.           }
  199.         if (cutoff)        /* can cut this corner off */
  200.           {
  201.           int iv0, iv1, iv2, iv3;
  202.           if (convex & (oc < pp->nv-2 ) )    
  203.           /* can cut off 4 vertices */
  204.             {
  205.         iv0 = oc;
  206.         iv1 = (oc+1)%n;
  207.         iv2 = (oc+2)%n;
  208.         iv3 = (oc+3)%n;
  209.         PP->n_vertices = 4;
  210.         PP->v[0] = pp->vlist[iv0];
  211.         PP->v[1] = pp->vlist[iv1];
  212.         PP->v[2] = pp->vlist[iv2];
  213.         PP->v[3] = pp->vlist[iv3];
  214.         if (push(PP) == 0)
  215.                 OOGLError(1,"anytoucd: unable to push polygon\n");
  216.             oc++;
  217.             oc++;
  218.         }
  219.           else 
  220.             {
  221.         iv0 = oc;
  222.         iv1 = (oc+1)%n;
  223.         iv2 = (oc+2)%n;
  224.         PP->n_vertices = 3;
  225.         PP->v[0] = pp->vlist[iv0];
  226.         PP->v[1] = pp->vlist[iv1];
  227.         PP->v[2] = pp->vlist[iv2];
  228.         if (push(PP) == 0)
  229.                 OOGLError(1,"anytoucd: unable to push polygon\n");
  230.             oc++;
  231.         }
  232.     
  233.           }
  234.       }
  235.     }    
  236.     while (oc < pp->nv)
  237.     {
  238.     newpoly->vlist[nc] = pp->vlist[oc];
  239.     HPt3Copy(&pp->vlistxy[oc], &newpoly->vlistxy[nc]);
  240.     oc++;
  241.     nc++;
  242.     }
  243.     newpoly->new = 0;
  244.     newpoly->nv = nc;
  245.  
  246.     /* if nothing got chopped, or if what's left
  247.      * has only 1 or 2 vertices */
  248.     if (newpoly->nv == pp->nv || newpoly->nv <= 2)
  249.     {
  250. /*
  251.     fprintf(stderr,"chopup:Unable to cut a corner\n");
  252. */
  253.     OOGLFree(newpoly);
  254.     return(NULL);
  255.     }
  256.  
  257.     else    return(newpoly);
  258.     }
  259.   }
  260. }
  261.  
  262.     Poly *CP, thisPoly;
  263.  
  264. main(argc, argv)    int argc; char **argv;
  265. {
  266.     register polygon *ncp, *cp, thispolygon;
  267.     int i, nv, pcountold, pcountnew;
  268.     char type[64];
  269.     HPoint3 vd;
  270.     Geom *thisgeom;
  271.     PolyList *thispl, *newpl;
  272.     Vertex *vlist[4];
  273.     Transform id;
  274.  
  275.     TmIdentity(id);
  276.     thisgeom = GeomFLoad(stdin,NULL);
  277.     thispl = (PolyList*)AnyToPL(thisgeom, id);
  278.     newpl = (PolyList*)GeomCopy((Geom*)thispl);
  279.     if (initstack() == 0) 
  280.     OOGLError(1,"anytoucd: unable to init stack\n");
  281.  
  282.     cp = OOGLNew(polygon);
  283.     CP = &thisPoly;
  284.     /* at most 4 vertices in each face */
  285.     for (pcountold = 0; pcountold < thispl->n_polys; ++pcountold)    
  286.     {
  287.     myconvert(&thispl->p[pcountold], cp);
  288.     bcopy(&thispl->p[pcountold], CP, sizeof(Poly));
  289.         CP->v = vlist;
  290.     OOGLNew(polygon);
  291.        while ( (ncp = chopup(cp, CP)) != NULL ) 
  292.         {
  293.         if (debug)
  294.         fprintf(stderr,"Chop up: calling again\n");
  295.  
  296.         OOGLFree(cp);
  297.         cp = ncp; 
  298.         }
  299.     }
  300.     /* now get the list of polygons from the stack */
  301.     thispl->n_polys = getsize();
  302.     thispl->p = getstack();
  303.  
  304.     /* now print out the stuff in ucd format */
  305.     /* GeomFSave(thispl, stdout, NULL); */
  306.     {
  307.     FILE *fp = stdout;
  308.     int num_nodes, 
  309.     num_node_data_comp = 0, 
  310.     node_data_comp[2],
  311.     num_cells, 
  312.     num_cell_data_comp = 0, 
  313.     total_node_comp = 0,
  314.     total_cell_comp = 0,
  315.     cell_data_comp[2],
  316.     i,j,n;
  317.     Poly *p;
  318.     Vertex *v, **vp;
  319.  
  320.     num_nodes = thispl->n_verts;
  321.     num_cells = thispl->n_polys;
  322.     if (thispl->flags & PL_HASVCOL) {
  323.     node_data_comp[0] = 4;    /* ColorA's : 4 component */
  324.     num_node_data_comp += 1;
  325.     total_node_comp += 4;
  326.     }
  327.     if (thispl->flags & PL_HASVN) {
  328.     node_data_comp[num_node_data_comp] = 3;
  329.     num_node_data_comp += 1;
  330.     total_node_comp += 3;
  331.     }
  332. #ifdef FOURD
  333.     if (thispl->geomflags & VERT_4D)    {
  334.     node_data_comp[num_node_data_comp] = 1;    /* ColorA's : 4 component */
  335.     num_node_data_comp += 1;
  336.     total_node_comp += 1;
  337.     }
  338. #endif
  339.     if (thispl->flags & PL_HASPCOL) {
  340.     cell_data_comp[0] = 4;    /* ColorA's : 4 component */
  341.     num_cell_data_comp += 1;
  342.     total_cell_comp += 4;
  343.     }
  344.     if (thispl->flags & PL_HASPN) {
  345.     cell_data_comp[num_cell_data_comp] = 3;
  346.     num_cell_data_comp += 1;
  347.     total_cell_comp += 3;
  348.     }
  349.     {
  350.     char *timestring;
  351.     long mytime;
  352.     time_t myt;
  353.     myt = time(&mytime);
  354.     timestring = ctime(&myt);
  355.     fprintf(fp,"#  Created by anytoucd on %s \n",timestring);
  356.     }
  357.  
  358.     fprintf(fp,"%d %d %d %d 0\n",num_nodes, num_cells, total_node_comp, total_cell_comp);
  359.     /* write out vertices */
  360.     /* what to do about 4D vertices? */
  361.     for (v = thispl->vl, i=0; i<thispl->n_verts; ++i, ++v)
  362. #ifdef FOURD
  363.     fprintf(fp,"%d %g %g %g\n",i+1,v->pt.x, v->pt.y, v->pt.z);
  364. #else
  365.     {
  366.     float w = v->pt.w;
  367.     if (w) w = 1.0/w;
  368.     fprintf(fp,"%d %g %g %g\n",i+1,w*v->pt.x, w*v->pt.y, w*v->pt.z);
  369.     }
  370. #endif
  371.     
  372.  
  373.     /* write out faces */
  374.     for (i=0, p = thispl->p; i<thispl->n_polys; ++i, ++p)    {
  375.     fprintf(fp,"%d 1 ",i+1);
  376.     n = p->n_vertices;
  377.     if (n==2)  fprintf(fp,"line ");    /* is this right? */
  378.     else if (n==3)  fprintf(fp,"tri ");
  379.     else if (n==4) fprintf(fp, "quad ");
  380.     /* else signal error */
  381.     else return;
  382.         for(vp = p->v; --n >= 0; vp++)
  383.                 fprintf(fp, "%d ", (*vp) - thispl->vl + 1);
  384.     fprintf(fp,"\n");
  385.     }
  386.     
  387.     if (num_node_data_comp) {
  388.         fprintf(fp,"%d ", num_node_data_comp);
  389.         for (i=0; i<num_node_data_comp; ++i)
  390.             fprintf(fp,"%d ", node_data_comp[i]);
  391.         fprintf(fp,"\n");
  392.     }
  393.  
  394.     if (thispl->flags & PL_HASVCOL)    fprintf(fp,"rgba, NULL\n");
  395.     if (thispl->flags & PL_HASVN)    fprintf(fp,"normal, NULL\n"); 
  396.     if (thispl->geomflags & VERT_4D)    fprintf(fp,"w, NULL\n");
  397.  
  398.     /* print vertex colors */
  399.     if (thispl->flags & PL_HASVCOL)        {
  400.         for (v = thispl->vl, i=0; i<thispl->n_verts; ++i, ++v)
  401.         fprintf(fp,"%d %g %g %g %g\n", i+1, v->vcol.r, v->vcol.g, v->vcol.b, v->vcol.a);
  402.     }
  403.     
  404.     /* print vertex normals */
  405.     if (thispl->flags & PL_HASVN)        {
  406.         for (v = thispl->vl, i=0; i<thispl->n_verts; ++i, ++v)
  407.         fprintf(fp,"%d %g %g %g\n", i+1, v->vn.x, v->vn.y, v->vn.z);
  408.     }
  409.  
  410. #ifdef FOURD
  411.     /* print fourth coordinate if present */
  412.     if (thispl->geomflags & VERT_4D)    {
  413.         for (v = thispl->vl, i=0; i<thispl->n_verts; ++i, ++v)
  414.         fprintf(fp,"%d %g\n", i+1, v->pt.w);
  415.     }
  416. #endif
  417.  
  418.     /* now process cell data */
  419.     if (num_cell_data_comp) {
  420.     fprintf(fp,"%d ", num_cell_data_comp);
  421.         for (i=0; i<num_cell_data_comp; ++i)
  422.             fprintf(fp,"%d ", cell_data_comp[i]);
  423.         fprintf(fp,"\n");
  424.     }
  425.     /* print labels */
  426.     if (thispl->flags & PL_HASPCOL)        fprintf(fp,"rgba, NULL\n");
  427.     if (thispl->flags & PL_HASPN)        fprintf(fp,"normal, NULL\n");
  428.  
  429.     /* print face colors */
  430.     if (thispl->flags & PL_HASPCOL)        {
  431.         for (p = thispl->p, i=0; i<thispl->n_polys; ++i, ++p)
  432.         fprintf(fp,"%d %g %g %g %g\n", i+1, p->pcol.r, p->pcol.g, p->pcol.b, p->pcol.a);
  433.     }
  434.     
  435.     /* print face normals */
  436.     if (thispl->flags & PL_HASPN)        {
  437.         for (p = thispl->p, i=0; i<thispl->n_polys; ++i, ++p)
  438.         fprintf(fp,"%d %g %g %g\n", i+1, p->pn.x, p->pn.y, p->pn.z);
  439.     }
  440.     }
  441. }
  442.  
  443.  
  444.